package predictors;

import java.io.IOException;

import database.Database;

import objects.MessageCodes;
import objects.predictors.AttrInfo;
import objects.predictors.Co2Info;
import objects.predictors.ProbaInfo;
import objects.shared.WorkPacket;
import objects.shared.Message;
import objects.user.UserInfo;

import predictors.co2predictor.CO2PredictorImpl;
import predictors.queuetimepredictor.AttributeMatcherImpl;
import predictors.resourcepredictor.ResourcePredictorImpl;

import utils.Utils;
import jobqueue.JobQueueInfo;

public class SubmitJob implements Runnable {
	UserInfo userInfo;
	WorkPacket workPacket;

	public SubmitJob(UserInfo u, WorkPacket wp) {
		this.userInfo = u;
		this.workPacket = wp;
	}

	public void run() {
		try {
			if(userInfo.getAllOnlineClusters().isEmpty())
			{
				userInfo.sendMessage(new Message(MessageCodes.NO_ONLINE_CLU));
				//return;
			}
			if (workPacket.cluster == -1) {
				Utils.out("<IN PRED>");
				switch (workPacket.opt) {
				case 0: {
					doQueueTimeOpt();
					break;
				}
				case 1: {
					doResourcePredictorOpt();
					break;
				}
				case 2: {
					doCO2EmissionsOpt();
					break;
				}
				}
			} else {
				userInfo.clusterMap.get(workPacket.cluster).sendMessage(workPacket);
			}
			userInfo.workPackets.add(workPacket);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void doCO2EmissionsOpt() throws Exception, IOException {
		Co2Info co2info = CO2PredictorImpl
				.GetAvgLowestEmissionDateInTimeRange(workPacket.optRange);
		ProbaInfo probaInfo = ResourcePredictorImpl.GetHighestProbability(
				workPacket, co2info.date, 0);
		Utils.jobQueue.InsertJob(new JobQueueInfo(workPacket, probaInfo, userInfo));
		co2info.setCluster(probaInfo.cluster);
		workPacket.cluster = probaInfo.cluster;
		co2info.jobId = workPacket.uniqueId;
		userInfo.sendMessage(co2info);
	}

	private void doResourcePredictorOpt() throws Exception, IOException {
		ProbaInfo probaInfo = ResourcePredictorImpl
				.GetHighestProbability(workPacket);
		Utils.jobQueue.InsertJob(new JobQueueInfo(workPacket, probaInfo, userInfo));
		probaInfo.h_prob.jobId = workPacket.uniqueId;
		Utils.out(probaInfo.h_prob);
		userInfo.sendMessage(probaInfo.h_prob);
	}

	private void doQueueTimeOpt() throws Exception, IOException {
		AttrInfo attrInfo = AttributeMatcherImpl.GetLowestQtime(workPacket, userInfo);
		//Utils.out("JOB SUBMISSION: "+i.jobname+" "+i.low_bound+" "+i.cluster);
		if(userInfo.clusterMap.get(attrInfo.getCluster()).isConnected)
		{
			userInfo.clusterMap.get(attrInfo.getCluster()).sendMessage(workPacket);
			userInfo.sendMessage(attrInfo);
		}
		else
		{
			Utils.out("+ Cannot send request: cluster not connected");
			userInfo.sendMessage(new Message(MessageCodes.ERR, "Error: '"+ workPacket.jobname+"' target host disconnected during job submission process!"));
		}
	}

}
